34. Prueba de progreso 1ºC

Lee atentamente el enunciado de la prueba. El enunciado consiste en una serie de ejercicios que deben realizarse en un mismo archivo Python. Todas las funciones deben definirse en el mismo archivo y no debe incuirse ningún fragmento de código de prueba. Las entregas deberán ser trabajo original del alumno que realiza la entrega.

No se permite la comunicación con otras personas durante el examen. Se permiten libros, apuntes y búsquedas en Internet.

34.1. 1. Convolución de señales

Dadas dos señales de tiempo discreto, definidas como secuencias de valores reales \(u(k)\) y \(v(k)\) se define la convolución de ambas señales como:

\[w[n] = \sum_k u[k]\, v[n-k]\]

Nota: Una señal :math:`u[k]` se modela como una lista ``u`` con los números reales desde :math:`u[0]` hasta :math:`u[m-1]` siendo ``m = len(u)``. Todos los demás elementos se asume que valen 0. Es decir :math:`u[k] = 0, forall k notin {0..m}`.

  1. Definir una función ``elem`` con dos parámetros. El primer parámetro es una lista ``s`` conteniendo una señal discreta. El segundo parámetro es un entero ``k`` que indica un índice de elemento. La función debe devolver ``s[k]`` si ``k`` está en el rango de índices válidos para la lista ``s`` o ``0.0`` en caso contrario.
  2. Definir una función ``conv_elem`` con tres parámetros. Los dos primeros parámetros corresponden a las señales ``u`` y ``v``. El tercer parámetro es un entero ``n``. La función debe devolver el resultado de la ecuación definida arriba. Es decir, debe devolver el elemento ``n``-simo de la convolución de ``u`` y ``v``. Se sugiere utilizar la función ``elem`` para evitar tener que considerar casos especiales.
  3. Definir una función ``convolucion`` con dos parámetros que corresponden a las señales ``u`` y ``v`` y devuelve la lista de números reales resultado de la convolución de ambas señales. La longitud de la convolución de ``u`` y ``v`` es ``len(u) + len(v) - 1``.

34.1.1. Ejemplo de funcionamiento

u = [ 1., 2., 1., 2., 1., 2., 1., 2. ]
v = [ 1., 2., 3., 2., 1. ]
print convolucion(u,v)

[1.0, 4.0, 8.0, 12.0, 13.0, 14.0, 13.0, 14.0, 12.0, 10.0, 5.0, 2.0]
def elem(signal,k):
    if k >= len(signal) or k < 0:
        return 0.
    return signal[k]

def conv_elem(u, v, n):
    sum = 0.
    for k in range(len(u)):
        sum += elem(u,k)*elem(v,n-k)
    return sum

def convolucion(u,v):
    return [ conv_elem(u,v,i) for i in range(len(u)+len(v)-1) ]

La función convolucion también se puede hacer sin list comprehensions.

def convolucion(u,v):
    c = []
    for i in range(len(u)+len(v)-1):
        c.append(conv_elem(u,v,i))
    return c

34.2. 2. Piedra, papel o tijera

Piedra, papel o tijera es un juego en el que dos jugadores eligen una de esas tres opciones a la vez. El que gana depende de lo elegido por ambos:

  • La piedra gana a las tijeras (las despunta).
  • Las tijeras ganan al papel (lo cortan).
  • El papel gana a la piedra (la tapa).
  • Dos iguales empatan.

Hacer una función ganador que tenga dos parámetros de tipo cadena de texto. Cada parámetro puede contener una de estas tres palabras piedra, papel, o tijera. La función debe devolver un número indicando cuál de los dos gana. Si el primero gana devolverá un 1. Si el segundo gana devolverá un 2. Si empatan devolverá un 0.

34.2.1. Ejemplo de funcionamiento

print ganador('piedra','tijera')
1
print ganador('piedra','papel')
2
print ganador('tijera','tijera')
0

La forma más sencilla de hacerlo (desde mi punto de vista) es con un diccionario. Veamos cuáles son las distintas posibilidades de partidas en las que no hay empate.

opciones = ['piedra', 'papel', 'tijera']
juegos_posibles = [ (i,j) for i in opciones for j in opciones if i != j ]
print(juegos_posibles)
[('piedra', 'papel'), ('piedra', 'tijera'), ('papel', 'piedra'), ('papel', 'tijera'), ('tijera', 'piedra'), ('tijera', 'papel')]

Ya solo tenemos que decir cuál es el ganador de estas posibilidades en una lista y componer el diccionario:

def ganador(a,b):
    opciones = ['piedra', 'papel', 'tijera']
    posibles = [ (i,j) for i in opciones for j in opciones if i != j ]
    gana = [ 2, 1, 1, 2, 2, 1 ]
    ganadores = dict(zip(posibles, gana))
    if (a,b) in ganadores:
        return ganadores[(a,b)]
    return 0

También se puede hacer sin diccionario. Contemplamos primero el caso de que sean iguales y luego la mitad de los casos en los que a y b están ordenados según la secuencia piedra, papel, tijera. Para los demás casos llamamos a ganador con los parámetros invertidos y corregimos el resultado.

def ganador(a,b):
    if a == b: return 0
    if a == 'piedra' and b == 'papel':
        return 2
    if a == 'piedra' and b == 'tijera':
        return 1
    if a == 'papel' and b == 'tijera':
        return 2
    return 2 if ganador(b,a) == 1 else 1

La última línea también se puede poner como una lista indexada por el resultado.

def ganador(a,b):
    if a == b: return 0
    if a == 'piedra' and b == 'papel':
        return 2
    if a == 'piedra' and b == 'tijera':
        return 1
    if a == 'papel' and b == 'tijera':
        return 2
    return [0, 2, 1][ganador(b,a)]

34.3. Rúbrica de evaluación

Puntos totales: 10 puntos:

  • 1.1 Función elem: 2.5 puntos
  • 1.2 Función conv_elem: 2.5 puntos
  • 1.3 Función convolucion: 2.5 puntos
  • 2 Función ganador: 2.5 puntos

Penalizaciones:

  • Errores de sintaxis: 100% de los puntos de la función
  • Errores de ejecución (excepciones): 50% de los puntos de la función
  • Errores en límites de recorridos: 20% de los puntos de la función
  • Código repetitivo: 10% de los puntos de la función
Next Section - 35. Distancia Minkowski